# -*- mode: makefile -*-
#
# Mongoose OS for ESP8266
#
# GC_DEBUG: if "true" (default) enables string ASN checks
# STACK_GUARD: if "true" (default) enables soft stack guard
# SSL: chooses SSL library to use. Currently onle "mbedTLS" is supported
# HEAP_LOG: if "1", compiles ESP firmware with heap logging feature: there are
#           logging wrappers for malloc and friends. You can later view heap
#           map by `tools/heaplog_viewer/heaplog_viewer.html`
#
MAKEFLAGS += --warn-undefined-variables
.DEFAULT_GOAL := all

APP ?= mongoose-os
APP_PLATFORM = esp8266
APP_CFLAGS ?=
APP_CXXFLAGS ?=
APP_EXTRA_SRCS ?=
FFI_SYMBOLS ?=
# List of app source files, globs are supported
APP_SOURCES ?=
# List of include dirs, in addition to dirs from APP_SOURCES
APP_INCLUDES ?=
# List of app files to put into the device's filesystem, globs are supported
APP_FS_FILES ?=
# List of static libs (.a) which are parts of the app
APP_BIN_LIBS ?=

# NOTE: those two are deprecated. Use APP_SOURCES and APP_FS_FILES instead.
APP_MODULES ?=
APP_FS_PATH ?=

BUILD_LIB_NAME ?= lib.a

# For backward compatibility, convert old APP_MODULES and APP_FS_PATH into
# new APP_SOURCES and APP_FS_FILES
ifneq "$(APP_MODULES)" ""
APP_SOURCES += $(foreach m,$(APP_MODULES),$(m)/*.c $(m)/*.cpp)
endif
ifneq "$(APP_FS_PATH)" ""
APP_FS_FILES += $(foreach m,$(APP_FS_PATH),$(m)/*)
endif

# Get list of dirs which contain sources and filesystem files
APP_SOURCE_DIRS = $(sort $(dir $(APP_SOURCES)))
APP_FS_DIRS = $(sort $(dir $(APP_FS_FILES)))

MGOS_DEBUG_UART = 0

APP_PATH := $(CURDIR)

MGOS_PATH ?= ../../..
include $(MGOS_PATH)/fw/common.mk

COMMON_ESP_PATH ?= $(COMMON_PATH)/platforms/esp/src
COMMON_ESP8266_PATH ?= $(COMMON_PATH)/platforms/esp8266
MGOS_ESP8266_PATH ?= $(MGOS_PATH)/fw/platforms/esp8266
MBEDTLS_PATH ?= /opt/cs_mbedtls
SPIFFS_PATH ?= $(COMMON_PATH)/spiffs
UMM_MALLOC_PATH ?= $(COMMON_PATH)/umm_malloc
BOOTLOADER_PATH ?= $(COMMON_ESP8266_PATH)/rboot
ESPTOOL2 = $(BUILD_DIR)/esptool2
# Enable heap allocation logging - every malloc/free is logged.
MGOS_ENABLE_HEAP_LOG ?= 0
# In addition to logging allocations, print call traces for them.
# This instruments every function and increases code size significantly.
MGOS_ENABLE_CALL_TRACE ?= 0
MGOS_ESP8266_RTOS ?= 0

MGOS_UPDATE_BOOT_LOADER ?= false

FLASH_SIZE ?= 4194304
FS_BLOCK_SIZE = 4096
FS_PAGE_SIZE = 256
FS_ERASE_SIZE = 4096

RF_CAL_DATA_SIZE = 0x1000
SYS_PARAMS_SIZE = 0x4000

BUILD_DIR ?= $(CURDIR)/.build
RBOOT_BUILD_DIR ?= $(BUILD_DIR)/rboot
FW_STAGING_DIR ?= $(BUILD_DIR)/fw_temp
FW_DIR ?= $(CURDIR)/firmware
GEN_DIR ?= $(BUILD_DIR)/gen

# Absolutize all paths which can be given by the caller
override BUILD_DIR := $(abspath $(BUILD_DIR))
override FW_STAGING_DIR := $(abspath $(FW_STAGING_DIR))
override FW_DIR := $(abspath $(FW_DIR))
override GEN_DIR := $(abspath $(GEN_DIR))

LWIP_BUILD_DIR = $(BUILD_DIR)/lwip

FS_STAGING_DIR = $(BUILD_DIR)/fs
FW_SECTS = .text .data .rodata
FW_USER_ARGS = -quiet -bin -boot2

# SSL can be None or mbedTLS
SSL ?= mbedTLS
include $(COMMON_ESP8266_PATH)/common.mk

MGOS_ESP_SRC_PATH = $(MGOS_ESP8266_PATH)/src

MGOS_SRCS += cs_file.c cs_rbuf.c \
             mgos_config_util.c \
             mgos_core_dump.c \
             mgos_dlsym.c \
             mgos_event.c \
             mgos_gpio.c \
             mgos_hw_timers.c \
             mgos_init.c \
             mgos_time.c \
             mgos_timers.c \
             mgos_mmap_esp.c \
             mgos_mongoose.c \
             mgos_sys_config.c $(notdir $(MGOS_CONFIG_C)) $(notdir $(MGOS_RO_VARS_C)) \
             mgos_system.c \
             mgos_uart.c \
             mgos_utils.c \
             mgos_vfs.c \
             mgos_vfs_dev.c \
             mgos_vfs_dev_ram.c \
             mgos_vfs_fs_spiffs.c \
             cs_crc32.c \
             rboot-bigflash.c rboot-api.c \
             json_utils.c \
             umm_malloc.c \
             frozen.c

MGOS_SRCS += esp_config.c \
             esp_coredump.c \
             esp_debug.c \
             esp_exc.c \
             esp_flash_writer.c \
             esp_fs.c \
             esp_gpio.c \
             esp_hal.c \
             esp_heap_trace.c \
             esp_hw_timers.c \
             esp_hw_wdt.c \
             esp_libc.c \
             esp_main.c \
             esp_periph.c \
             esp_uart.c \
             esp_updater.c \
             esp_vfs_dev_sysflash.c

MGOS_SRCS += $(notdir $(foreach m,$(SPIFFS_PATH) $(COMMON_ESP8266_PATH),$(wildcard $(m)/*.c)))
APP_SRCS := $(notdir $(foreach m,$(APP_SOURCES),$(wildcard $(m)))) $(APP_EXTRA_SRCS)
APP_BIN_LIB_FILES := $(foreach m,$(APP_BIN_LIBS),$(wildcard $(m)))

MGOS_FEATURES ?=

VPATH = $(MGOS_VPATH) $(APP_SOURCE_DIRS) $(MGOS_SRC_PATH) $(MONGOOSE_PATH) \
        $(FROZEN_PATH) $(UMM_MALLOC_PATH) \
        $(BOOTLOADER_PATH)/rboot/appcode $(COMMON_PATH) $(COMMON_PATH)/mg_rpc \
        $(MGOS_ESP_SRC_PATH) $(SPIFFS_PATH) $(COMMON_ESP8266_PATH) \
        $(COMMON_ESP_PATH)
IPATH = $(MGOS_IPATH) $(sort $(APP_SOURCE_DIRS) $(APP_INCLUDES)) \
        $(SPIFFS_PATH) $(MGOS_ESP8266_PATH)/include \
        $(BOOTLOADER_PATH)/rboot $(SDK_PATH)/include/lwip \
        $(SDK_PATH) $(SDK_PATH)/include \
        $(COMMON_ESP8266_PATH) $(COMMON_ESP_PATH) \
        $(MGOS_ESP_SRC_PATH) $(COMMON_PATH)/mg_rpc
LPATH = $(SDK_PATH)/lib $(BUILD_DIR)/lwip

include $(MGOS_PATH)/fw/src/mgos_features.mk

# libraries used in this project, mainly provided by the SDK
SDK_LIBS = c crypto espnow gcc main net80211 pp phy stdc++ wpa wpa2
LIBS = $(addprefix -l,$(SDK_LIBS))

SHIMS = -DNDEBUG

MGOS_ESP_FEATURES = '-DUMM_ONFREE(ptr, size)=memset(ptr, 0xfa, size)'

MINIZ_FLAGS = -DMINIZ_NO_STDIO -DMINIZ_NO_TIME -DMINIZ_NO_ARCHIVE_APIS \
              -DMINIZ_NO_ARCHIVE_APIS -DMINIZ_NO_ZLIB_APIS \
              -DMINIZ_NO_ZLIB_COMPATIBLE_NAMES

MG_FEATURES ?= $(MG_FEATURES_TINY) -DMG_ESP8266 \
               -DMG_ENABLE_FILESYSTEM -DMG_ENABLE_DIRECTORY_LISTING \
               -DMG_NET_IF=MG_NET_IF_LWIP_LOW_LEVEL -DMG_MODULE_LINES \
               -DCS_DISABLE_MD5 -DMG_EXT_MD5 \
               -DMG_EXT_SHA1

FEATURES_EXTRA ?=
FEATURES = $(MG_FEATURES) $(MGOS_FEATURES) $(MGOS_ESP_FEATURES) \
           $(FEATURES_EXTRA) \
           -DCS_ENABLE_SPIFFS \
           -DBOOT_BIG_FLASH -DESP_UMM_ENABLE \
           -DMGOS_VFS_DEFINE_LIBC_REENT_API \
           -DMGOS_VFS_DEFINE_LIBC_DIR_API \
           -DMGOS_VFS_DEFINE_DIRENT \
           -DMG_LOCALS

MEMORY_FLAGS = -DFS_MAX_OPEN_FILES=5

.PHONY: all clean build-lib

MGOS_CFLAGS = -DMGOS_APP=\"$(APP)\" \
              -DMGOS_MAX_NUM_UARTS=2 \
              -DMGOS_NUM_GPIO=16 \
              -DC_DISABLE_BUILTIN_SNPRINTF

MGOS_LIB = $(BUILD_DIR)/mongoose-os.a
MGOS_CONFIG_C = $(GEN_DIR)/mgos_config.c
MGOS_CONFIG_DEFAULTS_JSON = $(GEN_DIR)/conf0.json
MGOS_CONFIG_SCHEMA_JSON = $(GEN_DIR)/mgos_config_schema.json
MGOS_RO_VARS_C = $(GEN_DIR)/mgos_ro_vars.c
MGOS_RO_VARS_SCHEMA_JSON = $(GEN_DIR)/mgos_ro_vars_schema.json
BUILD_INFO_C = $(GEN_DIR)/build_info.c
BUILD_INFO_O = $(BUILD_DIR)/build_info.c.o
BUILD_INFO_JSON = $(GEN_DIR)/build_info.json
MG_BUILD_INFO_C = $(GEN_DIR)/mg_build_info.c
MG_BUILD_INFO_O = $(BUILD_DIR)/mg_build_info.c.o
FFI_EXPORTS_C = $(GEN_DIR)/ffi_exports.c
FFI_EXPORTS_O = $(BUILD_DIR)/ffi_exports.c.o
GENFILES_FLAG = $(BUILD_DIR)/genfiles.done
GENFILES_LIST = $(MGOS_CONFIG_C) $(MGOS_RO_VARS_C)
IMAGE_HEADER_SIZE = 0
MAP_FILE = $(BUILD_DIR)/$(APP).elf.map
BREAKDOWN_FILE = $(BUILD_DIR)/breakdown.txt
FS_IMG = $(FW_STAGING_DIR)/fs.bin

ifeq "$(MGOS_ESP8266_RTOS)" "1"
  SDK_PATH = /opt/Espressif/ESP8266_RTOS_SDK
  MGOS_SRCS += esp_exc_rtos.c
  MGOS_CFLAGS += -DRTOS_SDK
  LWIP_LIB =
  LWIP_PATH = $(SDK_PATH)/lwip
  SDK_LIBS += freertos lwip mirom
  IPATH += $(SDK_PATH)/include/espressif \
           $(SDK_PATH)/extra_include \
           $(SDK_PATH)/include/lwip/ipv4 \
           $(SDK_PATH)/include/lwip/ipv6
  LD_SCRIPT_TEMPL = $(MGOS_ESP8266_PATH)/ld/rtos.ld
  LDFLAGS += -Wl,--wrap=user_fatal_exception_handler \
             -Wl,--wrap=ShowCritical
else
  SDK_PATH = /opt/Espressif/ESP8266_NONOS_SDK
  MGOS_SRCS += esp_exc_non_os.c
  MGOS_CFLAGS += -DLWIP_OPEN_SRC \
                 -DCS_MMAP -DSPIFFS_ON_PAGE_MOVE_HOOK=mgos_vfs_mmap_spiffs_on_page_move_hook
  LWIP_LIB = $(LWIP_BUILD_DIR)/liblwip_cs.a
  LWIP_PATH = /opt/Espressif/cs_lwip
  SDK_LIBS += m
  IPATH += $(LWIP_PATH)/src/include \
           $(LWIP_PATH)/src/include/ipv4 \
           $(LWIP_PATH)/espressif/include
  LD_SCRIPT_TEMPL = $(MGOS_ESP8266_PATH)/ld/non_os.ld

$(LWIP_LIB): $(LWIP_PATH)
	$(Q) mkdir -p $(abspath $(LWIP_BUILD_DIR))
	$(Q) $(MAKE) -C $(LWIP_PATH) -j3 all \
		APP=liblwip_cs BUILD_DIR=$(abspath $(LWIP_BUILD_DIR)) \
		COMMON_ESP8266_PATH=$(COMMON_ESP8266_PATH) \
		CFLAGS_EXTRA="$(HEAP_LOG_FLAGS)"
endif

ifeq "$(SSL)" "mbedTLS"
  IPATH += $(MBEDTLS_PATH)/include
  MGOS_SRCS += esp_crypto.c
  MGOS_ESP_FEATURES += -DMG_ENABLE_SSL -DMG_SSL_IF=MG_SSL_IF_MBEDTLS \
                       -DMG_SSL_IF_MBEDTLS_FREE_CERTS \
                       -DMG_SSL_IF_MBEDTLS_MAX_FRAG_LEN=1024 \
                       -DMBEDTLS_X509_CA_CHAIN_ON_DISK
  MBEDTLS_CFLAGS = $(CFLAGS)
  MGOS_CONF_SCHEMA += $(MGOS_ESP_SRC_PATH)/esp_mbedtls_config.yaml
  ifeq "$(MGOS_HAVE_ATCA)" "1"
    MBEDTLS_CFLAGS += -DMBEDTLS_ECP_ATCA -DMBEDTLS_X509_CA_CHAIN_ON_DISK -I$(ATCA_PATH)/lib
    SSL_LIBS = $(addprefix $(MBEDTLS_PATH)/library/,libmbedcrypto_atca.a libmbedtls_atca.a libmbedx509_atca.a)
  else
    SSL_LIBS = $(addprefix $(MBEDTLS_PATH)/library/,libmbedcrypto.a libmbedtls.a libmbedx509.a)
  endif

$(SSL_LIBS):
	$(Q) $(MAKE) -j4 -C $(MBEDTLS_PATH)/library $(notdir $@) \
		CC=$(CC) AR=$(AR) \
		CFLAGS="$(MBEDTLS_CFLAGS)"
else
  SSL_LIBS =
endif

MGOS_OBJS = $(addprefix $(BUILD_DIR)/,$(MGOS_SRCS:=.o)) \
            $(BUILD_DIR)/esp_exc_vectors.S.o \
            $(BUILD_DIR)/esp_nsleep100.S.o
APP_OBJS = $(addprefix $(BUILD_DIR)/,$(APP_SRCS:=.o))

BOOT_LOADER_BIN = $(RBOOT_BUILD_DIR)/rboot.bin
APP_BIN = $(BUILD_DIR)/$(APP).bin
APP_ELF = $(BUILD_DIR)/$(APP).elf
LD_SCRIPT = $(GEN_DIR)/$(APP0_ADDR).ld
LD_WRAPPERS =
HEAP_LOG_FLAGS =

ifneq "${MGOS_ENABLE_HEAP_LOG}${MGOS_ENABLE_CALL_TRACE}" "00"
  HEAP_LOG_FLAGS += -DMGOS_ENABLE_HEAP_LOG
  LD_WRAPPERS += -Wl,--wrap=umm_calloc \
                 -Wl,--wrap=umm_malloc \
                 -Wl,--wrap=umm_realloc \
                 -Wl,--wrap=umm_free
endif
ifeq "${MGOS_ENABLE_CALL_TRACE}" "1"
  MGOS_SRCS += cs_heap_trace.c
  HEAP_LOG_FLAGS += -finstrument-functions -DCALL_TRACE_SIZE=33 -DMGOS_ENABLE_CALL_TRACE
endif

IMAGE_HEADER_SIZE = 0x10

# Flash layout configuration.
BOOT_LOADER_ADDR ?= 0x0
BOOT_CONFIG_ADDR ?= 0x7000
BOOT_CONFIG_WRITE_ADDR ?= $(BOOT_CONFIG_ADDR)
# Sys params must be at the end of flash, this is where SDK looks for (and writes!) them and it's not configurable.
SYS_PARAMS_ADDR = $(shell printf "0x%05x" "$$(($(FLASH_SIZE) - $(SYS_PARAMS_SIZE)))")
# RF calibration data sector location is configurable, but we also keep it at the end, just above sys params.
FW_RF_CAL_DATA_ADDR = $(shell printf "0x%05x" "$$(($(FLASH_SIZE) - $(SYS_PARAMS_SIZE) - $(RF_CAL_DATA_SIZE)))")
MKSPIFFS ?= /usr/local/bin/mkspiffs8

ifeq ("$(FLASH_SIZE)", "1048576")
#
# 1MB (8Mb) layout:
#
# 0x000000 - rBoot        |
# 0x007000 - boot cfg     |
# 0x008000 - app (844K)   |
# 0xdb0000 - fs (128K)    |
# 0x0fb000 - rf cal       |
# 0x0fc000 - sys params   |
FS_SIZE ?= 131072
ROM_SIZE = $(shell printf "0x%05x" "$$((0x100000 - $(APP0_ADDR) - $(FS_SIZE) - $(RF_CAL_DATA_SIZE) - $(SYS_PARAMS_SIZE) - $(IMAGE_HEADER_SIZE)))")
APP0_ADDR = 0x8000
FS0_ADDR  = $(shell printf "0x%05x" "$$((0x100000 - $(FS_SIZE) - $(RF_CAL_DATA_SIZE) - $(SYS_PARAMS_SIZE)))")
APP1_ADDR = 0
FS1_ADDR = 0
else
ifeq ("$(FLASH_SIZE)", "2097152")
#
# 2MB (16Mb) layout
#
# 0x000000 - rBoot        | 0x100000 - free (32K)   |
# 0x007000 - boot cfg     |                         |
# 0x008000 - app0 (844K)  | 0x108000 - app1 (844K)  |
# 0x0db000 - fs0 (128K)   | 0x1db000 - fs1 (128K)   |
# 0x0fb000 - free (20K)   | 0x1fb000 - rf cal       |
#                         | 0x1fc000 - sys params   |
FS_SIZE ?= 131072
ROM_SIZE = $(shell printf "0x%05x" "$$((0x100000 - ($(APP0_ADDR) % 0x100000) - $(FS_SIZE) - $(RF_CAL_DATA_SIZE) - $(SYS_PARAMS_SIZE) - $(IMAGE_HEADER_SIZE)))")
APP0_ADDR = 0x8000
FS0_ADDR  = $(shell printf "0x%05x" "$$((0x100000 - $(FS_SIZE) - $(RF_CAL_DATA_SIZE) - $(SYS_PARAMS_SIZE)))")
APP1_ADDR = 0x108000
FS1_ADDR  = $(shell printf "0x%05x" "$$((0x200000 - $(FS_SIZE) - $(RF_CAL_DATA_SIZE) - $(SYS_PARAMS_SIZE)))")
else
#
# 4MB (32Mb) or larger layout
#
# 0x000000 - rBoot        | 0x100000 - app0 (1024K) | 0x200000 - app1 (1024K) | 0x200000 - free (1004K) |
# 0x007000 - boot cfg     |                         |                         |                         |
# 0x008000 - fs0 (256K)   |                         |                         |                         |
# 0x048000 - fs1 (256K)   |                         |                         |                         |
# 0x880000 - free (480K)  |                         |                         |                         |
#                         |                         |                         | 0x2fb000 - rf cal       |
#                         |                         |                         | 0x2fc000 - sys params   |
FS_SIZE ?= 262144
ROM_SIZE = $(shell printf "0x%05x" "$$((0x100000 - $(IMAGE_HEADER_SIZE)))")
FS0_ADDR  = 0x8000
FS1_ADDR = $(shell printf "0x%05x" "$$(($(FS0_ADDR) + $(FS_SIZE)))")
APP0_ADDR = 0x100000
APP1_ADDR = 0x200000
endif
endif

RF_CAL_DATA_INIT = $(FW_STAGING_DIR)/$(FW_RF_CAL_DATA_ADDR).bin
BOOTLOADER_FLAGS = -DFW1_ADDR=$(APP0_ADDR) \
                   -DFW2_ADDR=$(APP1_ADDR) \
                   -DFW1_FS_ADDR=$(FS0_ADDR) \
                   -DFW2_FS_ADDR=$(FS1_ADDR) \
                   -DFS_SIZE=$(FS_SIZE) \
                   -DFW_SIZE=$(ROM_SIZE) \
                   -DBOOT_CONFIG_ADDR=$(BOOT_CONFIG_ADDR)

FW_MANIFEST = $(FW_STAGING_DIR)/manifest.json

INCDIRS = $(addprefix -I,$(IPATH)) -I$(GEN_DIR)
LIBDIRS = $(addprefix -L,$(LPATH))

C_CXX_FLAGS += $(MEMORY_FLAGS) $(SHIMS) $(FEATURES) \
               -DFW_RF_CAL_DATA_ADDR=$(FW_RF_CAL_DATA_ADDR) \
               -DFW_ARCHITECTURE=$(APP_PLATFORM) \
               $(MGOS_CFLAGS) $(CFLAGS_EXTRA) \
               $(HEAP_LOG_FLAGS) $(MINIZ_FLAGS) $(BOOTLOADER_FLAGS)

CFLAGS += $(APP_CFLAGS)
CXXFLAGS += $(APP_CXXFLAGS)

$(BUILD_DIR) $(FW_DIR) $(FW_STAGING_DIR) $(GEN_DIR):
	$(vecho) "MKDIR $@"
	$(Q) mkdir -p $@

MGOS_ADC_MODE_VDD ?= 0
# If MGOS_ADC_MODE_VDD == 1, we want to measure VDD33 internal (system_get_vdd33).
# Then the 107th byte in esp_init_data_default.bin (named as vdd33_const)
# must be set to 255 (0xFF).
# So we change the path to the esp_init_data_default.bin file
ifeq "$(MGOS_ADC_MODE_VDD)" "1"
  SDK_INIT_DATA_PATH = $(MGOS_ESP8266_PATH)
else
  SDK_INIT_DATA_PATH = $(SDK_PATH)
endif
CFLAGS += -DMGOS_ADC_MODE_VDD=$(MGOS_ADC_MODE_VDD)

# Main output product: firmware files.
FW_PARTS = boot:addr=$(BOOT_LOADER_ADDR),src=$(BOOT_LOADER_BIN),update=$(MGOS_UPDATE_BOOT_LOADER) \
           boot_cfg:addr=$(BOOT_CONFIG_WRITE_ADDR),size=0x1000,fill=0xff \
           fw:addr=$(APP0_ADDR),src=$(APP_BIN) \
           fs:src=$(FS_IMG),type=fs,addr=$(FS0_ADDR),fs_size=$(FS_SIZE),fs_block_size=$(FS_BLOCK_SIZE),fs_page_size=$(FS_PAGE_SIZE),fs_erase_size=$(FS_ERASE_SIZE) \
           rf_cal_data:addr=$(FW_RF_CAL_DATA_ADDR),size=$(RF_CAL_DATA_SIZE),fill=0xff \
           sys_params:type=sys_params,src=$(SDK_INIT_DATA_PATH)/bin/esp_init_data_default_v08.bin,addr=$(SYS_PARAMS_ADDR)

include $(MGOS_PATH)/common/scripts/fw_meta.mk

all: $(FW_DIR) $(BUILD_DIR) $(GEN_DIR) $(FW_STAGING_DIR) $(FW_ZIP) $(BREAKDOWN_FILE)

$(FW_MANIFEST): $(BOOT_LOADER_BIN) $(APP_BIN) $(FS_IMG) $(FS_FILES)

$(APP_BIN): $(APP_ELF) $(BUILD_DIR)/esptool2
	$(vecho) "FW    $< -> $@"
	$(Q) $(ESPTOOL2) $(FW_USER_ARGS) $< $@ $(FW_SECTS)

$(BREAKDOWN_FILE): $(APP_ELF)
	$(vecho) "Generating breakdown"
	$(Q) python $(COMMON_PATH)/tools/breakdown.py $(MAP_FILE) .text,.irom0.text .bss,.data,.rodata /opt > $(BREAKDOWN_FILE)

# -- Linking.

# Link the main ELF output file.
BIN_PARTS = $(BUILD_DIR)/esp_cache.c.o $(APP_OBJS) $(FFI_EXPORTS_O) $(BUILD_INFO_O) $(MG_BUILD_INFO_O) $(MGOS_LIB) $(ATCA_LIB) $(LWIP_LIB) $(SSL_LIBS) $(APP_BIN_LIB_FILES)
$(APP_ELF): $(BIN_PARTS) $(LD_SCRIPT)
ifeq "$(MGOS_ESP8266_RTOS)" "1"
	$(OBJCOPY) --weaken-symbol printf --weaken-symbol puts /opt/Espressif/esp-open-sdk/xtensa-lx106-elf/xtensa-lx106-elf/lib/libc.a
endif
	$(call link,$(BIN_PARTS) $(LIBS) $(LD_WRAPPERS))

$(BUILD_DIR)/dummy_main.c: $(APP_OBJS) $(MGOS_ESP8266_PATH)/Makefile.build
	$(vecho) "GEN   $@"
	$(Q) echo "void user_init(void){}; " \
            "void system_restart_local(){};" \
            "void __wrap_user_fatal_exception_handler(){}; " \
            "void __cyg_profile_func_enter(void *this_fn, void *call_site){(void) this_fn; (void) call_site;}" \
            "void __cyg_profile_func_exit(void *this_fn, void *call_site){(void) this_fn; (void) call_site;}" > $@

# Main app lib.
$(MGOS_LIB): $(MGOS_OBJS)
	$(vecho) "AR    $@"
	$(Q) $(AR) cru $@ $^

# This rule is for normal (pre-existing) C sources from VPATH.
$(BUILD_DIR)/%.c.o: %.c $(GENFILES_FLAG)
	$(compile)

# This rule is for normal (pre-existing) C++ sources from VPATH.
$(BUILD_DIR)/%.cpp.o: %.cpp $(GENFILES_FLAG)
	$(compile_cxx)

# Assembly sources.
$(BUILD_DIR)/%.S.o: %.S $(GENFILES_FLAG)
	$(vecho) "AS    $< -> $@"
	$(Q) $(CC) -c -mtext-section-literals $(MGOS_CFLAGS) -o $@ $<

# This one is for generated sources in build/gen directory.
$(BUILD_DIR)/%.c.o: $(GEN_DIR)/%.c $(GENFILES_FLAG)
	$(compile)

# Common gathering point for all generated files.
# Except build info, which is special because it depends on objects.
$(GENFILES_FLAG): $(GENFILES_LIST)
	$(Q) touch $@

# Generate linker script.
$(LD_SCRIPT): $(LD_SCRIPT_TEMPL)
	$(eval _IROM0ADDR=$(shell printf "0x%08x" $$((0x40200000 + ($(basename $(notdir $@)) % 0x100000) + $(IMAGE_HEADER_SIZE)))))
	$(eval _IROM0SIZE=$(ROM_SIZE))
	$(vecho) "GEN   $^ ($(_IROM0SIZE) @ $(_IROM0ADDR)) -> $@"
	$(Q) mkdir -p $(GEN_DIR)
	$(Q) sed -e 's/_IROM0ADDR/$(_IROM0ADDR)/; s/_IROM0SIZE/$(_IROM0SIZE)/' $^ > $@

include $(MGOS_PATH)/common/scripts/build_info.mk
include $(MGOS_PATH)/common/scripts/ffi_exports.mk
include $(MGOS_PATH)/fw/src/mgos_config.mk
include $(MGOS_PATH)/fw/src/spiffs.mk

MGOS_CONF_SCHEMA += $(MGOS_ESP_SRC_PATH)/esp_sys_config.yaml

$(MGOS_CONFIG_C): $(MANIFEST_FINAL)

$(FFI_EXPORTS_C): $(APP_FS_FILES)
	$(call gen_ffi_exports,$@,$(FFI_SYMBOLS),$(filter %.js,$(FS_FILES)))

# In ffi exports file we use fake signatures: void func(void), and it conflicts
# with the builtin functions like fopen, etc.
$(FFI_EXPORTS_O): CFLAGS += -fno-builtin

# Regenerate build info if there are changes in objects.
$(BUILD_INFO_C) $(BUILD_INFO_JSON): $(APP_OBJS) $(MGOS_OBJS)
	$(call gen_build_info,$@,$(APP_PATH),$(APP_BUILD_ID),$(APP_VERSION),,$(BUILD_INFO_C),$(BUILD_INFO_JSON))

$(MG_BUILD_INFO_C): $(MGOS_OBJS)
	$(call gen_build_info,$@,$(MGOS_PATH)/fw,,,mg_,$(MG_BUILD_INFO_C),)

# Pull in auto-generated .c dependencies (if any).
-include $(wildcard $(BUILD_DIR)/*.d)

# Build lib.a

$(BUILD_DIR)/$(BUILD_LIB_NAME): $(BUILD_DIR) $(APP_OBJS)
	$(vecho) "AR    $@"
	$(AR) cru $@ $(APP_OBJS)

# -- Filesystem.

$(FS_IMG): $(APP_FS_DIRS) $(FS_FILES) $(MGOS_CONFIG_C) $(MGOS_RO_VARS_C)
	$(call mkspiffs,$(FS_SIZE),$(FS_BLOCK_SIZE),$(FS_PAGE_SIZE),$(FS_ERASE_SIZE))

#
# Auxiliary targets.
#

$(ESPTOOL2):
	$(Q) $(MAKE) --no-print-directory -C $(BOOTLOADER_PATH)/esptool2 BUILD_DIR=$(abspath $(BUILD_DIR))

$(BOOT_LOADER_BIN): $(ESPTOOL2) $(GENFILES_LIST)
	$(Q) rm -rf $(RBOOT_BUILD_DIR) && mkdir -p $(RBOOT_BUILD_DIR)
	$(Q) $(MAKE) --no-print-directory -C $(BOOTLOADER_PATH)/rboot -f rboot.mk \
		RBOOT_BUILD_BASE=$(abspath $(RBOOT_BUILD_DIR)) \
		RBOOT_GEN_BASE=$(abspath $(GEN_DIR)) \
		ESPTOOL2=$(abspath $(ESPTOOL2)) SDK_BASE=$(SDK_PATH) \
		RBOOT_BIG_FLASH=1 CFLAGS_EXTRA="$(BOOTLOADER_FLAGS)"

clean:
	$(Q) rm -rf $(BUILD_DIR) $(FW_DIR)
ifeq "$(SSL)" "mbedTLS"
	$(Q) $(MAKE) -C $(MBEDTLS_PATH)/library clean
endif
